package studio.raptor.dispatcher.server.sort;

import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import java.util.Map;
import java.util.Set;
import studio.raptor.databus.command.EventMetaData;
import studio.raptor.dispatcher.common.constant.BoActionType;
import studio.raptor.dispatcher.server.sort.EventRelationship.Relationship;

/**
 * @author jack
 * @since 1.0
 */
public class DefaultSortRule extends SortRule {

  private EventMetaData event;
  private Relationship relationship;

  private Set<String> dependIds = Sets.newHashSet();


  public DefaultSortRule(EventMetaData event, Relationship relationship) {
    this.event = event;
    this.relationship = relationship;
  }


  @Override
  public DefaultSortRule sortByParty() {
    Long[] partyIds = event.getCustId();
    String orderId = event.getBusinessNo();
    String orderTypdIds = event.getOrderTypeIds();
    Map<Long, String> depend = relationship.getPartyRule();
    SetMultimap<String, Long> dependReverse = relationship.getPartyRuleReverse();

    if (null == partyIds || orderTypdIds == null) {
      return this;
    }

    boolean addCust = false;
    if (orderTypdIds.contains(BoActionType.ADD_CUST)) {
      addCust = true;
    }

    for (int i = 0, size = partyIds.length; i < size; i++) {
      Long partyId = partyIds[i];
      if (depend.containsKey(partyId)) {
        String dependId = depend.get(partyId);
        dependIds.add(dependId);
        dependReverse.remove(dependId, partyId);
      }
      if (addCust) {
        dependReverse.put(orderId, partyId);
        depend.put(partyId, orderId);
      }
    }

    return this;
  }


  @Override
  public DefaultSortRule sortByModifyParty() {
    Long[] partyIds = event.getCustId();
    String orderId = event.getBusinessNo();
    String orderTypdIds = event.getOrderTypeIds();
    Map<Long, String> depend = relationship.getModifyPartyRule();
    SetMultimap<String, Long> dependReverse = relationship.getModifyPartyRuleReverse();

    if (partyIds == null || orderTypdIds == null) {
      return this;
    }

    if (orderTypdIds.contains(BoActionType.MODIFY_CUST)) {
      for (Long partyId : partyIds) {
        if (depend.containsKey(partyId)) {
          dependIds.add(depend.get(partyId));
          dependReverse.remove(orderId, partyId);
        }
        dependReverse.put(orderId, partyId);
        depend.put(partyId, orderId);
      }
    }

    return this;
  }


  @Override
  public DefaultSortRule sortByAcct() {
    Long[] acctIds = event.getAcctId();
    String orderId = event.getBusinessNo();
    String orderTypdIds = event.getOrderTypeIds();
    Map<Long, String> depend = relationship.getAccountRule();
    SetMultimap<String, Long> dependReverse = relationship.getAccountRuleReverse();

    if (null == acctIds) {
      return this;
    }

    boolean addOrModify = false;
    if (orderTypdIds.indexOf(BoActionType.ADD_ACCT) >= 0) {
      addOrModify = true;
    }
    for (int i = 0, size = acctIds.length; i < size; i++) {
      Long acctId = acctIds[i];
      if (depend.containsKey(acctId)) {
        String dependId = depend.get(acctId);
        dependIds.add(dependId);
        dependReverse.remove(dependId, acctId);
      }
      if (addOrModify) {
        dependReverse.put(orderId, acctId);
        depend.put(acctId, orderId);
      }
    }
    return this;
  }

  @Override
  public DefaultSortRule sortByMofifyAcct() {

    Long[] acctIds = event.getAcctId();
    String orderId = event.getBusinessNo();
    String orderTypdIds = event.getOrderTypeIds();
    Map<Long, String> depend = relationship.getModifyAccountRule();
    SetMultimap<String, Long> dependReverse = relationship.getModifyAccountRuleReverse();

    if (null == acctIds || null == dependReverse) {
      return this;
    }

    if (orderTypdIds.indexOf(BoActionType.MODIFY_ACCT) > 0) {
      for (int i = 0, size = acctIds.length; i < size; i++) {
        Long acctId = acctIds[i];
        if (depend.containsKey(acctId)) {
          String dependId = depend.get(acctId);
          dependIds.add(dependId);
          dependReverse.remove(dependId, acctId);
        }
        dependReverse.put(orderId, acctId);
        depend.put(acctId, orderId);
      }
    }
    return this;
  }


  @Override
  public DefaultSortRule sortByProd() {
    Long[] prodIds = event.getProdInstId();
    String orderId = event.getBusinessNo();
    Long[] offerProds = event.getOfferProdId();

    Map<Long, String> depend = relationship.getProdRule();
    SetMultimap<String, Long> dependReverse = relationship.getProdRuleReverse();

    //销售品变更的时候，有依赖产品的，需要插入到依赖关系
    if (null != offerProds) {
      for (int i = 0, size = offerProds.length; i < size; i++) {
        Long offerProdId = Long.valueOf(offerProds[i]);
        if (depend.containsKey(offerProdId)) {
          dependIds.add(depend.get(offerProdId));
        }
      }
    }

    if (null == prodIds) {
      return this;
    }
    for (Long prodId : prodIds) {
      if (depend.containsKey(prodId)) {
        dependIds.add(depend.get(prodId));
        dependReverse.remove(orderId, prodId);
      }
      depend.put(prodId, orderId);
      dependReverse.put(orderId, prodId);
    }

    return this;
  }

  @Override
  public DefaultSortRule sortByOffer() {

    Long[] offers = event.getOfferInstId();
    String orderId = event.getBusinessNo();
    Map<Long, String> depend = relationship.getOfferRule();
    SetMultimap<String, Long> dependReverse = relationship.getOfferRuleReverse();

    if (null == offers) {
      return this;
    }

    for (int i = 0, size = offers.length; i < size; i++) {
      Long offerId = offers[i];
      if (depend.containsKey(offerId)) {
        String dependId = depend.get(offerId);
        dependIds.add(dependId);
        dependReverse.remove(dependId, offerId);
      }
      depend.put(offerId, orderId);
      dependReverse.put(orderId, offerId);
    }
    return this;
  }

  public Relationship getRelationship() {
    return relationship;
  }

  public void setRelationship(Relationship relationship) {
    this.relationship = relationship;
  }

  public Set<String> getDependIds() {
    return dependIds;
  }


}
